﻿#include "Opcodes.h"
#include "DataBase.h"
#include "SocketServer.h"
#include "World.h"
#include <iostream>

static OpcodeHandler* _OpcodeHandler = nullptr;
static std::mutex OpcodeLocker;

OpcodeHandler::OpcodeHandler()
{

}

OpcodeHandler::~OpcodeHandler()
{
}

OpcodeHandler* OpcodeHandler::GetInstance()
{
	if (_OpcodeHandler == nullptr)
	{
		ThreadLocker Locker(OpcodeLocker);
		if (_OpcodeHandler == nullptr)
		{
			_OpcodeHandler = new OpcodeHandler();
		}
	}
	return _OpcodeHandler;
}

std::string OpcodeHandler::SplitPacket(WorldPacket& _WorldPacket)
{
	std::string getbak = "";
	std::string panduan = "";
	for (int i = 0; i < _WorldPacket.length() + 1000; i++)
	{
		if (_WorldPacket.empty())
			break;
		panduan = _WorldPacket.at(0);
		if (panduan != "|")
		{
			getbak += panduan;
			_WorldPacket.erase(0, 1);
		}
		else
		{
			_WorldPacket.erase(0, 1);
			break;
		}
	}
	return getbak;
}

void OpcodeHandler::HandlePlayerLoginOpcode(WorldPacket& _packet, HSocket _HSocket)
{
	std::string Account = SplitPacket(_packet);
	std::string PassWord = SplitPacket(_packet);
	char msg[255];
	_snprintf(msg, 255, "SELECT id FROM account WHERE username = '%s'", Account.c_str());
	Result::Qurey result = sDataBase->GetResult(LoginDataBase, msg);
	if (!result.empty())
	{
		char rev[255];
		_snprintf(rev, 255, "%d|%d", SMSG_PLAYER_LOGIN_CHECK_ACCOUNT, LoginSuccess);
		SocketServer::GetInstance()->sendMessage(_HSocket, rev, sizeof(rev));


		std::cout << "player login with account : " << Account << "  password : " << PassWord << std::endl;

		WorldSession* Temp = sWorld->CreateNewSession(_HSocket);
		Temp->SetAccountID(atoi(result[0].at(0).c_str()));
		Temp->SetSocketId(_HSocket);
	}
	else
	{
		char rev[255];
		_snprintf(rev, 255, "%d|%d", SMSG_PLAYER_LOGIN_CHECK_ACCOUNT, LoginFailed);
		SocketServer::GetInstance()->sendMessage(_HSocket, rev, sizeof(rev));
		std::cout << "player login with account : " << Account << "  password : " << PassWord << std::endl;
	}
}

void OpcodeHandler::HandlePlayerBuildOpcode(WorldPacket& _worldpacket, HSocket _socket)
{
	//回执格式 操作码 角色总数 当前角色数 角色guid 角色名称 角色职业
	WorldSession* TempSession = sWorld->FindSession(_socket);
	if (TempSession)
	{
		char msg[255];
		_snprintf(msg, 255, "SELECT guid,name,class FROM characters WHERE account = %u", TempSession->GetAccountID());
		Result::Qurey result = sDataBase->GetResult(LoginDataBase, msg);
		if (!result.empty())
		{
			char msg[255];
			int NumberOfCharacter = 1;
			for (Result::Qurey::iterator itr = result.begin(); itr != result.end(); itr++)
			{
				std::string back = "4|";
				back += buildpacket(result.size());
				uint32 guid = atoi(itr->second.at(0).c_str());
				std::string name = itr->second.at(1).c_str();
				name += "|";
				back += buildpacket(NumberOfCharacter);
				back += buildpacket(guid);
				back += name.c_str();
				back += buildpacket(atoi(itr->second.at(2).c_str()));
				NumberOfCharacter++;
				TempSession->AddMessageToQueue(back.c_str());
			}
		}
		else
		{
			std::string back = "4|";
			back += buildpacket(result.size());
			TempSession->AddMessageToQueue(back.c_str());
		}
	}
}

void OpcodeHandler::HandlePlayerGetCharacterDetail(WorldPacket& _WorldPacket, HSocket _Hsocket)
{
	//格式 操作码 图片地址,基础血量,基础攻击力,基础防御力,基础移动速度,等级
	WorldSession* TempSession = sWorld->FindSession(_Hsocket);
	uint32 guid = (uint32)atoi(SplitPacket(_WorldPacket).c_str());
	if (TempSession)
	{
		char msg[255];
		_snprintf(msg, 255, "SELECT url,base_heath,attackpower,defance,base_speed,level FROM characters_info WHERE guid = %u", guid);
		Result::Qurey result = sDataBase->GetResult(LoginDataBase, msg);
		if (!result.empty())
		{
			std::string BackString = "6|";
			std::string url = "";
			uint32 Heath = 0;
			uint32 AttackPower = 0;
			uint32 Defance = 0;
			uint32 Speed = 0;
			uint32 Level = 0;
			url = result[0].at(0).c_str();
			url += "|";

			Heath			= atoi(result[0].at(1).c_str());
			AttackPower		= atoi(result[0].at(2).c_str());
			Defance			= atoi(result[0].at(3).c_str());
			Speed			= atoi(result[0].at(4).c_str());
			Level			= atoi(result[0].at(5).c_str());

			BackString += url;
			BackString += buildpacket(Heath);
			BackString += buildpacket(AttackPower);
			BackString += buildpacket(Defance);
			BackString += buildpacket(Speed);
			BackString += buildpacket(Level);

			TempSession->AddMessageToQueue(BackString.c_str());
		}
	}
}

void OpcodeHandler::MessageComming(WorldPacket& _WorldPacket, HSocket _HSocket)
{
	Opcodes opcode = (Opcodes)atoi(SplitPacket(_WorldPacket).c_str());
	switch (opcode)
	{
	case OPCODE_NONE:
		break;
	case CMSG_PLAYER_LOGIN_CHECK_ACCOUNT:
		HandlePlayerLoginOpcode(_WorldPacket, _HSocket);
		std::cout << _WorldPacket << endl;
		break;
	case SMSG_PLAYER_LOGIN_CHECK_ACCOUNT:
		break;
	case CMSG_SEND_BUILD_PLAYER_REQUIRE:
		HandlePlayerBuildOpcode(_WorldPacket, _HSocket);
		break;
	case SMSG_SEND_BUILD_PLAYER_REQUIRE:
		break;
	case CMSG_GET_CHARACTER_INFO:
		HandlePlayerGetCharacterDetail(_WorldPacket, _HSocket);
		break;
	case SMSG_GET_CHARACTER_INFO:
		break;
	case CMSG_PLAYER_GET_ACHMENT_DATA:
		break;
	case SMSG_PLAYER_GET_ACHMENT_DATA:
		break;
	case CMSG_NEXT_PACKET_REQUIRE:
		if (WorldSession* session = sWorld->FindSession(_HSocket))
		{
			session->SetCanRecvMessage(true);
		}
		break;
	}
}